/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package trace;

/**
 *
 * @author Julien Cassis
 */
public class predictorBuffer implements Runnable {
        private int M_BIT = 0x1fff;
        private final int HISTORY_TABLE_SIZE = 0x1fff;
        private int count = 0, misPrediction = 0;
        private Branch[] historyTable = new Branch[HISTORY_TABLE_SIZE + 1];
        private Reader traceFile;
        private Writer outputFile;
        private int bits;
        
        public predictorBuffer(Reader iFile,Writer oFile, int bits) {
            this.traceFile = iFile;
            this.outputFile = oFile;
            this.bits = bits;
            initialiseHistoryTable();
        }

        public predictorBuffer(Reader iFile,Writer oFile, int bits, int m) {
            this.traceFile = iFile;
            this.outputFile = oFile;
            this.bits = bits;
            this.M_BIT = (1<<(m+1)) - 1;
            initialiseHistoryTable();
        }

        private void initialiseHistoryTable(){
            for(int i=0;i<this.HISTORY_TABLE_SIZE;i++)
                historyTable[i] = null;
        }

        public void run(){
            String traceStr;
            String[] fileOption = new String[2];
            traceStr = traceFile.readLine();
            int index,outcome;
            long address;
            System.out.println("Starting NBIT: " + traceFile.filename + " " + bits);
            while(traceStr != null) {
                fileOption = Reader.parseString(traceStr);
                address = Long.parseLong(fileOption[0]);
                outcome = Integer.parseInt(fileOption[1]);
                index = getIndex(address);
                if(this.historyTable[index] == null){
                        this.historyTable[index] = new Branch(bits);
                }
                int prediction = this.historyTable[index].predictionBufferUpdate(outcome);
                if (prediction != outcome) misPrediction++;
                count++;
                traceStr = traceFile.readLine();
            }
            System.out.println("Done NBIT: " + traceFile.filename + " " + bits);
            summary();
            outputFile.close();
        }

        public int getIndex(long value){
            int index = 0;
            index = (int) value & this.M_BIT;
            return index;
        }

        public void summary(){
            int lcount = 1;
             this.outputFile.writeToFile("Index,Misprediction,Count");
            for(int i=0;i<HISTORY_TABLE_SIZE;i++){
                if(this.historyTable[i] != null){
                    this.outputFile.writeToFile(i + "," + this.historyTable[i].getMisPrediction() + "," + this.historyTable[i].getCount() + ",");
                    lcount++;
                }
            }
             this.outputFile.writeToFile("," + misPrediction + "," + count + "," + "=B"+(lcount+1)+"/C"+(lcount+1)+"*100");
             initialiseHistoryTable();
        }

}
